<?php

namespace plugin\admin\app\controller;

use app\services\RedisQueue;
use app\services\RequestService;
use plugin\admin\app\model\PriceLog;
use plugin\admin\app\model\RechargeLog;
use plugin\admin\app\model\Store;
use plugin\admin\app\model\VipPriceLog;
use plugin\admin\app\model\YbUser;
use support\Cache;
use support\Db;
use support\Log;
use support\Redis;
use support\Request;
use support\Response;
use plugin\admin\app\model\VipOrder;
use plugin\admin\app\controller\Crud;
use support\exception\BusinessException;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;

/**
 * 升级付费报表 
 */
class VipOrderController extends Crud
{

    protected $phone = '19163651992';
//    protected $phone = '17731053938';
    /**
     * @var VipOrder
     */
    protected $model = null;

    /**
     * 构造函数
     * @return void
     */
    public function __construct()
    {
        $this->model = new VipOrder;
    }

    public function select(Request $request): Response
    {
        [$where, $format, $limit, $field, $order] = $this->selectInput($request);
        $query = $this->doSelect($where, $field, $order)->orderBy('is_reward','desc');
        return $this->doFormat($query, $format, $limit);
    }

    protected function doFormat($query, $format, $limit): Response
    {
        $methods = [
            'select' => 'formatSelect',
            'tree' => 'formatTree',
            'table_tree' => 'formatTableTree',
            'normal' => 'formatNormal',
        ];
        $paginator = $query->paginate($limit);
        $total = $paginator->total();
        $items = $paginator->items();
        $total_price = VipPriceLog::where('appid','90F4F7FC5562A459D98F1C6B0FB82CF6')->value('price')??0;
        $total_price = RequestService::priceFormat($total_price);
        foreach ($items as $k => $v){
            $reward_order = Redis::lIndex('vip_order_list',0);
            $price = RequestService::priceFormat($v['price']);
            if (!empty($reward_order)){
                $reward_order = json_decode($reward_order,true);
                if ($v['id']==$reward_order['order_id']){
                    $items[$k]['progress'] = bcdiv($total_price,$price, 2)*100 . '%';
                }
            }
            if ($v['is_reward'] == 1){
                $items[$k]['progress'] = '100%';
            }
        }
        if (method_exists($this, "afterQuery")) {
            $items = call_user_func([$this, "afterQuery"], $items);
        }
        $format_function = $methods[$format] ?? 'formatNormal';
        return call_user_func([$this, $format_function], $items, $total,['total_price'=>$total_price??0]);
    }
    
    /**
     * 浏览
     * @return Response
     */
    public function index(): Response
    {
        return view('vip-order/index');
    }

    /**
     * 插入
     * @param Request $request
     * @return Response
     * @throws BusinessException
     */
    public function insert(Request $request): Response
    {
        if ($request->method() === 'POST') {
            $code = $request->post('smsCode');
            $path = $request->post('excel_file');
            // 文件是否存在
            if(empty($path) || !file_exists($path)){
                return $this->json(1, '请重新上传文件');
            }
            $sms = Cache::get($this->phone.'sms_code');
            if (empty($sms)){
                return $this->json(1, '请先发送验证码');
            }
            if ($code != $sms){
                return $this->json(1, '验证码错误');
            }
           return $this->uploadExcel($path);
        }
        return view('vip-order/insert',['phone'=>$this->phone]);
    }

    public function sendSms()
    {

//        $send_time = Cache::get($this->phone.'sms_code_time');
//        if (!empty($send_time)){
//            return $this->json(1, '请勿频繁发送');
//        }
        $statusStr = array(
            "0" => "短信发送成功",
            "-1" => "参数不全",
            "-2" => "服务器空间不支持,请确认支持curl或者fsocket，联系您的空间商解决或者更换空间！",
            "30" => "密码错误",
            "40" => "账号不存在",
            "41" => "余额不足",
            "42" => "帐户已过期",
            "43" => "IP地址限制",
            "50" => "内容含有敏感词"
        );
        $smsapi = "http://api.smsbao.com/";
        $user = "13111301970"; //短信平台帐号
        $pass = md5("fsc20020915"); //短信平台密码
        $code = rand(1000,9999);

        $content="【鼎鲜团】您的验证码为{$code}，在30分钟内有效。";//要发送的短信内容
        $phone = $this->phone;//要发送短信的手机号码
        $sendurl = $smsapi."sms?u=".$user."&p=".$pass."&m=".$phone."&c=".urlencode($content);
        $result =file_get_contents($sendurl) ;
        if ($result==0){
            Cache::set($phone.'sms_code',$code,1800);
            Cache::set($phone.'sms_code_time',time(),60);
        }
        return $this->json(0, $statusStr[$result]);
    }

    public function uploadExcelFile(Request $request)
    {
        $file = current($request->file());
        if (!$file || !$file->isValid()) {
            return $this->json(1, '未找到文件');
        }
        $data = $this->base($request, '/upload/files/' . date('Ymd'));
        return $this->json(0, '上传成功', $data);
    }

    public function uploadExcel($path)
    {
        $list = $this->excelImport($path,2);
        Db::beginTransaction();
        try {
            if (!empty($list)){
                foreach ($list as $item){
                    if (empty($item[8]) || empty($item[1])){
                        continue;
                    }
                    $vip_proportion = Cache::get('vip_proportion',20);
                    $rake_price = bcmul($item[8],($vip_proportion/100),2);
                    $appid = Cache::get($item[1]);
                    if (empty($appid)){
                        $appid = $this->getAppId($item[1]);
                        if (empty($appid)){
                            continue;
                        }
                    }
                    $create = [
                        'appid'=>$appid,
                        'customer_number' => $item[2],
                        'price' => $item[8],
                        'time' => $item[7],
                        'rake_price' => $rake_price,
                        'name' => $item[3],
                        'old_grade' => $item[4],
                        'now_grade' => $item[5],
                        'expiration_date' => $item[6]
                    ];
                    $order = VipOrder::where($create)->first();
                    if (empty($order)){
                        $order = VipOrder::create($create);
                        $create['reward_create_time'] = date('Y-m-d H:i:s');
                        $create['order_id'] = $order->id;
                        Redis::rPush('vip_order_list',json_encode($create));
                    }
                    $price_log = VipPriceLog::where('appid', $appid)->first();
                    if (!empty($price_log)){
                        if ($order->is_record == 0){
                            $price_log->increment('price',$rake_price);
                            $price_log->save();
                        }
                    }else{
                        $price_log = VipPriceLog::create([
                            'appid' => $appid,
                            'price' => $rake_price,
                        ]);
                    }
                    VipOrder::where('id', $order->id)->update(['is_record' => 1]);
                    $reward_order = Redis::lindex('vip_order_list',0);
                    if (!empty($reward_order)){
                        $reward_order = json_decode($reward_order,true);
                        $is_recharge = RechargeLog::where('vip_order_id',$reward_order['order_id'])->first();
                        if (!empty($is_recharge)){
                            Redis::lpop('vip_order_list');
                            continue;
                        }
                        if ($price_log->price >= $reward_order['price']){
                            RedisQueue::vipOrderReward($reward_order);
                            Redis::lpop('vip_order_list');
                            VipPriceLog::where('appid', $reward_order['appid'])->decrement('price', $reward_order['price']);
                        }
                    }
                }
            }
            Db::commit();
        }catch (\Throwable $e){
            Db::rollBack();
            Log::error('导入失败:'.$e->getMessage());
            return $this->json(1, '导入失败');
        }
        return $this->json(0, '导入成功');
    }

    public function getAppId($name)
    {
        $appid = Store::where('name',$name)->value('appid');
        Cache::set($name, $appid,3600);
        return $appid;
    }

    protected function base(Request $request, $relative_dir): array
    {
        $relative_dir = ltrim($relative_dir, '\\/');
        $file = current($request->file());
        if (!$file || !$file->isValid()) {
            throw new BusinessException('未找到上传文件', 400);
        }

        $admin_public_path = rtrim(config('plugin.admin.app.public_path', ''), '\\/');
        $base_dir = $admin_public_path ? $admin_public_path . DIRECTORY_SEPARATOR : base_path() . '/plugin/admin/public/';
        $full_dir = $base_dir . $relative_dir;
        if (!is_dir($full_dir)) {
            mkdir($full_dir, 0777, true);
        }

        $ext = $file->getUploadExtension() ?: null;
        $mime_type = $file->getUploadMimeType();
        $file_name = $file->getUploadName();
        $file_size = $file->getSize();

        if (!$ext && $file_name === 'blob') {
            [$___image, $ext] = explode('/', $mime_type);
            unset($___image);
        }

        $ext = strtolower($ext);
        $ext_forbidden_map = ['php', 'php3', 'php5', 'css', 'js', 'html', 'htm', 'asp', 'jsp'];
        if (in_array($ext, $ext_forbidden_map)) {
            throw new BusinessException('不支持该格式的文件上传', 400);
        }

        $relative_path = $relative_dir . '/' . bin2hex(pack('Nn', time(), random_int(1, 65535))) . ".$ext";
        $full_path = $base_dir . $relative_path;
        $file->move($full_path);
        $image_with = $image_height = 0;
        if ($img_info = getimagesize($full_path)) {
            [$image_with, $image_height] = $img_info;
            $mime_type = $img_info['mime'];
        }
        return [
            'url' => "/app/admin/$relative_path",
            'name' => $file_name,
            'realpath' => $full_path,
            'size' => $file_size,
            'mime_type' => $mime_type,
            'image_with' => $image_with,
            'image_height' => $image_height,
            'ext' => $ext,
        ];
    }

    /**
     * 更新
     * @param Request $request
     * @return Response
     * @throws BusinessException
    */
    public function update(Request $request): Response
    {
        if ($request->method() === 'POST') {
            return parent::update($request);
        }
        return view('vip-order/update');
    }

    public static function excelImport($filePath, $startRow = 1)
    {
        // 判断文件格式xlsx或xls
        $reader = new Xlsx();
        $reader->setReadDataOnly(true);
        if (!$reader->canRead($filePath)) {
            $reader = new Xls();
            $reader->setReadDataOnly(true);
            if (!$reader->canRead($filePath)) {
                throw new \Exception('文件格式不支持');
            }
        }

        $spreadsheet = $reader->load($filePath);
        $sheetCount = $spreadsheet->getSheetCount(); // 获取sheet的数量

// 获取所有的sheet表格数据
        $excleDatas = [];
        $emptyRowThreshold = 50; // 连续空行的阈值

        for ($i = 0; $i < $sheetCount; $i++) {
            $currentSheet = $spreadsheet->getSheet($i); // 读取excel文件中的第一个工作表
            $allColumn = $currentSheet->getHighestColumn(); // 取得最大的列号
            $allColumn = Coordinate::columnIndexFromString($allColumn); // 由列名转为列数('AB'->28)
            $allRow = $currentSheet->getHighestRow(); // 取得一共有多少行

            $arr = [];
            $emptyRowNum = 0;

            for ($currentRow = $startRow; $currentRow <= $allRow; $currentRow++) {
                $rowValues = [];
                for ($currentColumn = 1; $currentColumn <= $allColumn; $currentColumn++) {
                    $columnName = Coordinate::stringFromColumnIndex($currentColumn);
                    $cell = $currentSheet->getCell($columnName . $currentRow);
                    $rowValues[] = trim($cell->getValue());
                }
                // 统计连续空行
                if (empty($rowValues) && $emptyRowNum <= $emptyRowThreshold) {
                    $emptyRowNum++;
                } else {
                    $emptyRowNum = 0;
                }

                // 连续50行数据为空，不再读取后面行的数据，防止读满内存
                if ($emptyRowNum > $emptyRowThreshold) {
                    break;
                }

                $arr[$currentRow] = $rowValues;
            }

            $excleDatas[$i] = $arr; // 多个sheet的数组的集合
        }

//        return $excleDatas;
        // 这里我只需要用到第一个sheet的数据，所以只返回了第一个sheet的数据
        $returnData = $excleDatas ? array_shift($excleDatas) : [];

        // 第一行数据就是空的，为了保留其原始数据，第一行数据就不做array_fiter操作；
        $returnData = $returnData && isset($returnData[$startRow]) && !empty($returnData[$startRow]) ? array_filter($returnData) : $returnData;
        return $returnData;
    }

    public static function orderData($type = '')
    {
        // 高级会员数量
        $result['vip_count'] = VipOrder::count();
        // 已互助数量
        $result['reward_count'] = VipOrder::where('is_reward',1)->count();
        // 待发放奖励订单数量
        $result['reward_order_count'] = Redis::llen('vip_order_list');
        // 已互助金额
        $result['reward_price'] = VipOrder::where('is_reward',1)->sum('price');
        $result['order_total_price'] = VipOrder::sum('price');
        $result['order_total_price'] = RequestService::priceFormat($result['order_total_price']);
        $result['reward_price'] = RequestService::priceFormat($result['reward_price']);
        $reward_order = Redis::lindex('vip_order_list',0);
        if (!empty($reward_order)){
            $reward_order = json_decode($reward_order,true);
            $reward_order['customer_number'] = mask_string($reward_order['customer_number']);
             $reward_order['price'] = RequestService::priceFormat($reward_order['price']);
        }
        $total_price = VipPriceLog::where('appid','90F4F7FC5562A459D98F1C6B0FB82CF6')->value('price')??'0.00';
        if (!empty($type)){
            $result['progress'] = $total_price>0?bcdiv($total_price,$reward_order['price'],2)*100 .'%':'0%';
        }else{
            $result['progress'] = $result['vip_count']>0?bcdiv($result['reward_count'],$result['vip_count'],2)*100 .'%':'0%';

        }

        $result['reward_order'] = $reward_order;
        $result['total_price'] = $total_price;
        return $result;
    }

}
